#!/usr/bin/python

#  This program is free software.
#  You can redistribute it and/or modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation.
#  That is either version 2 of the License, or if you prefer any later version.

import pygst
import pygtk
import gtk
import gst
import glob
import threading
import gobject
import socket


'''Streamer Class. This class creates a stream to be sent to a client program.'''
class Streamer():
    def __init__(self, curDir, details):
    	self.hostname=details[0]
    	self.port=details[1]
        self._curDir = curDir
        self._fileType = '/*.mp3'
        self._playList = list() # this is how you create a list you don't
                                # know the size of at the start of the program

        
        # call method to create pipeline to stream
        self.create_playList() # create a play list
        self._mainloop = gobject.MainLoop()

	
        
    def create_streamer(self): # in the future this will also pass in an integer to be used as the list index
            
        # Old Playbin Code leave this here
        #self.pipln = gst.element_factory_make("playbin", "pipln")
        #self.pipln.set_property('uri', self._playList[0]) # first index

        # Just to test new file referencing
	
        self._pipeline = gst.Pipeline('serverpipeline')

      					
	self._fsrc = gst.element_factory_make('filesrc', 'fsrc') ## SERVER CODE	
	self._pipeline.add(self._fsrc) ## SERVER CODE
	self._fsrc.set_property('location', self._playList[0])	# is a list index so that we can support a play list ## SERVER CODE
        

	self._client = gst.element_factory_make('tcpclientsink', 'client') ## SERVER CODE
	self._pipeline.add(self._client) ## SERVER CODE
	self._client.set_property('host', self.hostname)## SEVER CODE
	self._client.set_property('port', self.port) ## SERVER CODE
	self._fsrc.link(self._client)
	self.prepare_stream()
	
	gobject.threads_init()
	
	

    def create_player(self) 	
        self._pipeline = gst.Pipeline('serverpipeline')
	self._decoder = gst.element_factory_make("decodebin", "decoder") 	
	self._decoder.connect("new-decoded-pad", self.onDynamicPad) 			
	self._pipeline.add(self._decoder) 									
	self._fsrc.link(self._decoder) 									
	self._convert = gst.element_factory_make("audioconvert", "convert")	
	self._pipeline.add(self._convert)										
	self._output = gst.element_factory_make("alsasink", "sink")			
	self._pipeline.add(self._output)
	self._convert.link(self._output)

	self.prepare_stream()
        gobject.threads_init()

    # creates a pad for the pipeline. do not remove
    def onDynamicPad(self, dbin, pad, islast):
        pad.link(self._convert.get_pad('sink'))

    def get_curDir(self):
        print self._curDir

    def create_playList(self):
        for files in glob.glob(self._curDir+self._fileType):
            self._playList.append(files)

    def clear_playList(self):
        self._playList = list()
        self.show_playList()

    def show_playList(self): # this method is only for use on the server
        if len(self._playList)==0 : # if the list is empty
            print 'Playlist is Empty'
        else:
            print self._playList

    # adds a folder to the playlist
    def add_to_playList(self):
        self.curDir = curDir
        self.create_playList()

    def set_curDir(self, curDir):
        self.curDir = curDir
        self.create_playList() # recreate the playlist with the new directory

    def play_stream(self):
       
        self._pipeline.set_state(gst.STATE_PLAYING)
        



    def stop_stream(self):
        self._pipeline.set_state(gst.STATE_NULL)

    def prepare_stream(self):
	self._pipeline.set_state(gst.STATE_READY)


class ServerInterface(threading.Thread):
    
    def __init__(self, streamerObj):
    	threading.Thread.__init__(self)
    	# this method overwrites the init method from the Thread class but then calls the method it overwrites.
    	# Might seem illogical but we need the init from Thread and we might need to do stuff here at some point in the future

	self._streamerObj = streamerObj

    def run(self):
        run = True 
        command = ''
        while run:
            command = raw_input('>>')
            if command == 'play':
                self.create_player()
                self.play_Handle()
            elif command == 'stream':
                self.create_streamer()
                self.play_Handle()
            elif command == 'stop':
                self.stop_Handle()
            elif command == 'exit':
                self.stop_Handle()
                run = False
            elif command == 'show playlist':
                self.showplayList_Handle()
            elif command == 'clear playlist':
                self.clearplayList_Handle()
            elif command == 'add to playlist':
                self.addtoplayList_Handle()
            elif command == 'help':
                self.help_Handle()
            else:
                print 'Invalid command'

            """event handelers"""
    def play_Handle(self):
        print 'Starting Stream'
        self._streamerObj.play_stream()
        
    def stop_Handle(self):
        print 'Stopping Stream'
        self._streamerObj.stop_stream()

    def help_Handle(self):
        print '"play stream" plays the stream'
        print '"stop stream" stops playing the stream'
        print '"exit stream" stops the program'
        print '"show playlist" shows the current playlist'
        print '"clear playlist" clears playlist'
        print '"add to playlist" adds folder to playlist'

    def showplayList_Handle(self):
        print 'Current Playlist'
        self._streamerObj.show_playList()

    def clearplayList_Handle(self):
        print 'Current Playlist'
        self._streamerObj.clear_playList()

    def addtoplayList_Handle(self):
        print ' ',
        curDir = raw_input()
        self._streamerObj.add_to_playList()
        
class ClientConnection(threading.Thread):
    def __init__(self, server, details, streamer):
        self.hostname=details[0]
        self.port=details[1]
	threading.Thread.__init__(self)
		
    def run(self):
        doMore = True
        while doMore:
            recievedData = server.recv(512)
            command = recievedData.split('\n')[:-1]
	    if command == 'PLAY':
                streamer.playHandle()
            elif command == 'STOP':
                streamer.stopHandle()
            elif command == 'QUIT':
                streamer.stopHandle()
                run = False

        

class ServerController(threading.Thread):
    def __init__(self):


        localIP = raw_input("What is the IP of your network adaptor?\n>>")
        port = int(raw_input("What port do you wish to bind to?\n>>"))
        server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)	# setup the socket type
        server.bind((localIP, port))					# bind to the specified port / address
        server.listen(1)						# listen until we get a connection
        channel, details = server.accept()	

	streamerObj = Streamer('./', details)
	streamerObj.start() # error here
	
        						# accept the connection
        #ClientConnection(channel, server, details, streamerObj).start()		# start the client listening thread
   
        interface = ServerInterface(streamerObj)
        interface.start()

        
controller = ServerController()
        

